import serial
import threading
from pynput import keyboard

# 配置串口参数
serial_port = 'COM5'  # 根据实际情况修改串口名，Windows下可能是"COM1", "COM2"等；Linux下为"/dev/ttyUSB0"等
baud_rate = 115200  # 波特率，根据实际设备要求设置

pressed_keys = {}  # 使用字典存储按键及其状态

def read_from_serial(ser):
    """从串口读取数据并打印"""
    while True:
        if ser.in_waiting > 0:
            received_data = ser.readline().decode('utf-8').rstrip()  # 读取一行数据并转换为字符串
            print(f"接收到的数据: {received_data}")

def send_key_event(key, is_press=True):
    try:
        key_name = key.char if hasattr(key, 'char') else key.name
        action = "按下" if is_press else "释放"
        
        # 检查是否需要发送数据
        if (is_press and not pressed_keys.get(key_name, False)) or (not is_press and pressed_keys.get(key_name, False)):
            key_data = (key_name + ('' if is_press else '~')).encode('utf-8') + b'\0'
            ser.write(key_data)  # 发送按键数据
            print(f"已发送数据: {action} {key_data}")
            
            # 更新按键状态
            pressed_keys[key_name] = is_press
    except Exception as e:
        print(f"发送数据时发生错误: {e}")

try:
    ser = serial.Serial(serial_port, baud_rate, timeout=1)
    print(f"成功打开串口: {ser.name}")

    # 启动一个线程用于持续读取串口数据
    threading.Thread(target=read_from_serial, args=(ser,), daemon=True).start()

    def on_press(key):
        send_key_event(key, True)

    def on_release(key):
        send_key_event(key, False)
        if key == keyboard.Key.esc:
            return False  # 返回False停止监听

    # 监听键盘按下事件
    with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()

except serial.SerialException as e:
    print(f"发生错误: {e}")

finally:
    if 'ser' in locals() and ser.is_open:
        ser.close()
        print("串口已关闭")